package com.uum.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uum.admin.pojo.entity.SysPermission;
import com.uum.admin.mapper.SysPermissionMapper;
import com.uum.admin.pojo.entity.SysRole;
import com.uum.admin.pojo.form.PermissionGenerate;
import com.uum.admin.pojo.query.PermissionPageQuery;
import com.uum.admin.pojo.vo.PermissionVO;
import com.uum.admin.service.SysMenuService;
import com.uum.admin.service.SysPermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.uum.admin.service.SysRoleService;
import com.uum.common.core.constant.GlobalConstants;
import com.uum.common.core.constant.RedisConstants;
import com.uum.web.util.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements SysPermissionService {

    private final RedisTemplate redisTemplate;
    private final SysRoleService sysRoleService;

    @Override
    @Transactional
    public void generatePerm(PermissionGenerate generate) {
        String serviceName = generate.getServiceName();
        String requestPath = generate.getRequestPath();
        String description = generate.getDescription();
        String btnPerm = generate.getBtnPerm();

        String[] descriptArr = {"查询", "删除", "修改", "新增"};
        String[] urlPermArr = {"GET:/?/page/**", "DELETE:/?/delete/**", "PUT:/?/update", "POST:/?/add"};
        String[] btnPermArr = {"sys:?:select", "sys:?:delete", "sys:?:update", "sys:?:add"};
        for (int i = 0; i < 4; i++) {
            SysPermission selectPerm = new SysPermission();
            selectPerm.setDescription(descriptArr[i] + description);
            String[] urlSplit = urlPermArr[i].split("\\?");
            selectPerm.setUrlPerm(urlSplit[0] + serviceName + requestPath + urlSplit[1]);
            String[] btnSplit = btnPermArr[i].split("\\?");
            selectPerm.setBtnPerm(btnSplit[0] + btnPerm + btnSplit[1]);
            selectPerm.setMenuId(generate.getMenuId());
            selectPerm.setOrderNum(0l);
            baseMapper.insert(selectPerm);
        }
    }

    @Override
    public boolean refreshPermRolesRules() {
        //清空权限角色
        redisTemplate.delete(Arrays.asList(RedisConstants.URL_PERM_ROLES_KEY));
        //清空用户信息
        Set userInfo = redisTemplate.keys(RedisConstants.USER_INFO_KEY + "*");
        if (!userInfo.isEmpty()) {
            redisTemplate.delete(userInfo);
        }
        List<SysPermission> permissions = this.listPermRoles(new QueryWrapper<SysPermission>());
        if (CollectionUtil.isNotEmpty(permissions)) {
            //初始化URL【权限->角色(集合)】规则
            List<SysPermission> urlPermList = permissions.stream()
                    .filter(item -> StrUtil.isNotBlank(item.getUrlPerm()))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(urlPermList)) {
                Map<String, List<String>> urlPermRoles = new HashMap<>();
                urlPermList.stream().forEach(item -> {
                    String perm = item.getUrlPerm();
                    List<String> roles = item.getRoles();
                    urlPermRoles.put(perm, roles);
                });
                redisTemplate.opsForHash().putAll(RedisConstants.URL_PERM_ROLES_KEY, urlPermRoles);
            }
        }
        return true;
    }

    @Override
    public List<SysPermission> listPermRoles(Wrapper<SysPermission> wrapper) {
        return this.baseMapper.listPermRoles(wrapper);
    }


    @Override
    public IPage<PermissionVO> page(PermissionPageQuery permissionPageQuery) {
        String menuId = permissionPageQuery.getMenuId();
        String description = permissionPageQuery.getDescription();
        int currentPage = permissionPageQuery.getCurrentPage();
        int pageSize = permissionPageQuery.getPageSize();

        Page<PermissionVO> page = new Page<>(currentPage, pageSize);
        List<PermissionVO> result = baseMapper.page(page,
                new QueryWrapper<PermissionVO>()
                        .eq("t1.menu_id", menuId)
                        .like(StrUtil.isNotBlank(description), "t1.description", description)
                        .orderByAsc("t1.order_num"));
        page.setRecords(result);
        return page;
    }


    @Override
    public List<SysPermission> listPermissionByMenuId(Long menuId) {
        return listPermission(menuId, null);
    }

    @Override
    public List<SysPermission> listPermissionByRoleIds(List<Long> roleIds) {
        return listPermission(null, roleIds);
    }

    public List<SysPermission> listPermission(Long menuId, List<Long> roleIds) {
        //判断是否超级管理员
        if (JwtUtils.isAdministrator()) {
            //查询所有按钮权限
            List<SysPermission> btnPermList = baseMapper.selectList(
                    new LambdaQueryWrapper<SysPermission>()
                            .eq(menuId != null, SysPermission::getMenuId, menuId)
            );
            return btnPermList;
        } else {
            //判断角色ID是否为空
            if (CollUtil.isEmpty(roleIds)) {
                roleIds = sysRoleService.getRoleIds();
            }
            //根据用户角色查询出所拥有的按钮权限
            List<SysPermission> btnPermList = listPermRoles(
                    new QueryWrapper<SysPermission>().in("t3.role_id", roleIds)
                            .eq(menuId != null, "t1.menu_id", menuId)
                            .groupBy("t1.id"));
            return btnPermList;
        }
    }


}
